DelphiSim Help Contents

Discrete Event Simulation with Borland’s Delphi2

v.1.05

By Roeland van der Spek

spekw@acm.org

© 1997

About DelphiSim

 	Intallation instructions

Registrating DelphiSim

TSimulation The Simulation component

TSimProcess The simulation processes object-type

Random streams and Random distributions

Collecting Statistics

Some simulation process types TMachine and TWaitProcess

Useful additional object types: TSemaphore and TOrderlist


DelphiSim registration

DelphiSim is inexpensive Shareware. The registration fee is $40. Models built with the unregistered versions are limited to 8 processes. After you register, I will send you a version without this limitation.

DelphiSim can be registerd via PSL (public software library):

https://www.pslweb.com/cgi-win/psl_ords.exe/ITEM30048

Or check out the DelphiSim home page for further registration instructions:

http://is.twi.tudelft.nl/~roeland/delphisim.html

Thanks a lot,

Roeland van der Spek


Installing delphisim

DelphiSim consists of a package containing the helpfile that you are reading now, some examples of simulation models built with DelphiSim, additional Pascal units and DelphiSim.dcu. This file is located in the Installation-subdirectory.

Add this unit to the your component library by clicking Component on the Delphi menubar, and then Install. Select Add. Browse to the file DelphiSim.dcu and select OK.

After you have done this, you will notice a new simulation tab in you component palette and you are all set!


About DelphiSim

DelphiSim is a collection of components and objects that enables users of Borland’s Delphi 2 to create Discrete Event Simulation models in their Delphi Environment. Thus creating a flexible way of integrating object orientied simulation models in any application.

A simulation model build with DelphiSim consists of a collection simulation processes. Each process is scheduled on an event list. The process at the top the event list is currently running. All others are suspended. When the active process is finished or if it suspends its operation, the next process in the event list becomes the active process. This continues until there are no more active processes left on the event list or until the maximum simulation time has expired.

DelphiSim is based around two object types: TSimulation and TSimProcess.


TSimulation

Unit: DelphiSim

TSimulation is a non visual component that controls the simulation. It must be installed on the component palette. The TSimulation component uses events to inform the user of the simulation status (see below).

Methods:

StartSimulation

SuspendSimulation

ResumeSimulation

TerminateSimulation

Properties:

SimTime

IsActive

IsSuspended

IsTerminated

RepsLeft

RepSize

Replications

Events:

OnSimInit

OnSimEnd

OnSuspend

OnReplication


StartSimulation

Object: TSimulation

Description: Starts the simulation.

When the simulation is started the OnSimInit   Event is called. At the end of every replication an OnReplication event is called. After the simulation has ended the OnSimEnd event is called.

If simulation is already active, this call will be ignored.

Example:

MySim.StartSimulation; {starts the simulation}


SuspendSimulation

Object: TSimulation

Description: Orders the simulation to suspend

Because the simulation processes are threads, the simulation will not suspend instantly. The simulation will be suspended after the OnSuspend Event has occurred. Calling the suspend method will cause the IsSuspended state to be true. Calling the resume method will resume the simulation.

If the simulation is not active or if the simulation is already suspended then this method will be ignored.

Example:

MySim.SuspendSimulation; {Orders the simulation to suspend}


ResumeSimulation

Object: TSimulation

Description: Resumes the simulation

After calling this method, the simulation will resume. The IsSuspended state will be set to false.

If the simulation is not suspended or active then a call to this method is ignored.

Example:

MySim.ResumeSimulation; {Orders the simulation to resume}


TerminateSimulation

Object: TSimulation

Description: Orders the simulation to end

Because simulation processes are implemented as threads, a call to this method will not terminate the simulation instantly. The simulation is not terminated before the OnSimEnd event has occurred. Calling this method will cause the terminated state to be true. The active state will be set to false after the simulation has in fact ended.

If the simulation is not active then a call to this method is ignored.

Example:

MySim.TerminateSimulation; {Orders the simulation to end}


SimTime

Object: TSimulation,TSimProcess

Type: Double

Access: Read only

Description: The current simulation time


IsActive
IsActive property

Object: TSimulation

Type: Boolean

Access: Read only

Description: If the simulation is running then IsActive is set to true

See also: IsSuspended , IsTerminated


IsSuspended
IsSuspended property

Object: TSimulation

Type: Boolean

Access: Read only

Description: If the simulation has been suspended then IsSuspended is set to true

See also: IsActive, IsTerminated


IsTerminated
IsTerminated property

Object: TSimulation

Type: Boolean

Access: Read only

Description: 	If the simulation has been ordered to terminated then IsTerminated is set to true. After the OnSimEnd event the IsTerminated is reset to false

See also: IsActive , IsSuspended


RepsLeft
RepsLeft property

Object: TSimulation

Type: Integer

Access: Read only

Description: RepsLeft contains the number of replications that the simulation still has to do.

See also: RepSize , Replications , OnReplication


Replications
Replications property

Object: TSimulation

Type: Integer

Access: Read/Write

Description: Replications contains the total number of replications for the simulation.

See also: RepSize, RepsLeft , OnReplication


RepSize
RepSize property

Object: TSimulation

Type: double

Access: Read/Write

Description: RepSize contains the length of each replication in the simulation.

See also: Replications , RepsLeft , OnReplication


OnSimInit
OnSimInit event

Object: TSimulation

Description:	This Event is called before each replication. Here all simulation processes must be created. This event must be handle by the user.

Example:

{

  create a simple model with a single machine and a single job

  generator

}

procedure TForm1.MySimInit(eventlist: TEventList);

begin

  MyTally.reset;  {clear the tally object}

  generator := TGenerator.create(Simulation1,0,'Generator');

  MyMachine := TMymachine.create(Simulation1,'The Machine');

end;


OnSimEnd
OnSimInit event

Object: TSimulation

Description:	This Event is called after the simulation has ended.

See also: TerminateSimulation


OnSuspend
OnSuspend event

Object: TSimulation

Description:	This Event is called after the simulation has suspended

See also: SuspendSimulation


OnReplication
OnReplication event

Object: TSimulation

Description:	This Event is called after each replication has ended. It can be used by the modeller to process the replication statistics.


TSimProcess

Unit: DelphiSim

All simulation processes must inherit from the TSimProcess class. TSimProcess is an abstract class, meaning that it is not possible to create instances of it. The reason for this is obvious: Each process does different things and therefore each process body will be different..

What a process does is described in the body method. This method must be overridden for each simulation process that is defined. The body method may contain any form of Delphi Pascal code, however restrictions apply for making VCL (visual component library) calls.

Constructor:

Create

Methods:

Body (must be overridden)

Passivate

Activate

ActivateAt

HoldFor

HoldUntil

Properties:

Active

Scheduled

Passive

SimTime


Create

Object: TSimProcess

Description: Creates a new simulation process

Syntax: create(L:TSimulation;StartTime:extended;naam:string);


Body

Object: TSimProcess

Description: 	Contains the description of your simulation process. This method is virtual and must be overridden by your processdefinition. Beware that restrictions apply when making calls to VCL objects. These calls must be synchronized with the main thread. (see example)

Example:

{

  we define our process of type TMyProcess

}

Type TMyProcess = Class(TSimProcess)

        procedure body; override;	{you must override body!}

        procedure HandleVCL;	{put your VCL Call here}

     end;

Implementation

{

  your process is in the body method. In this case we wait for

  2 time units, write some message to the form, wait another

  3 time units and then the process ends

}

Procedure TMyProcess.body;

begin

  holdfor(2);	{wait for 2 time units}

  synchronize(handleVCL);	{make a synchronized call to handle vcl}

  holdfor(3);	{wait another 3 units and then end}

end;

Procedure TmyProcess.HandleVCL;

begin

  Form1.label1.caption:=’synchronize your VCL calls’;

end;


Passivate

Object: TSimProcess

Description: 	Removes the process from the eventlist and makes it passive. It will not resume until it is activated.

See also: Active, Scheduled , Activate , ActivateAt , Passivate, HoldUntil , HoldFor

Example:

MyProc.Passivate   {This will make the process MyProc passive}


Activate

Object: TSimProcess

Description: 	Schedules the process to continue immediately.

See also: Active, Scheduled , Passive , ActivateAt , Passivate, HoldUntil , HoldFor

Example:

MyProc.Activate {This will make the process MyProc active}


ActivateAt
ActivateAT(T:Double)

Object: TSimProcess

Description: 	Schedules the process to continue at time T

See also: Active, Scheduled , Passive , Activate , Passivate,  HoldUntil , HoldFor

Example:

MyProc.ActivateAT(5) {Reschedule process for SimTime=5}


HoldFor
HoldFor(T:Double)

Object: TSimProcess

Description: 	Pauses the current process for T time units

See also: Active, Scheduled , Passive , Activate , ActivateAt , Passivate, HoldUntil

Example:

MyProc.HoldFor(5) {Reschedule process for SimTime+5}


HoldUntil
HoldUntil(T:Double)

Object: TSimProcess

Description: 	Pauses the current process until time T

See also: Active, Scheduled , Passive , Activate , ActivateAt , Passivate, HoldFor

Example:

MyProc.HoldUntil(7) {Reschedule process for SimTime=7}


Active
Active property

Object: TSimProcess

Type: Boolean

Access: Read only

Description: If true then the process is the active process.

See also: Scheduled, Passive


Scheduled
Scheduled property

Object: TSimProcess

Type: Boolean

Access: Read only

Description: If true then the process is scheduled to run at some time.

See also: Active, Passive


Passive
Passive property

Object: TSimProcess

Type: Boolean

Access: Read only

Description: If true then the process is passive and not scheduled to run again.

See also: Active, Scheduled , Passivate, Activate, ActivateAt


Random numbers and distributions
Random Numbers and Random Distributions

Unit: Random

DelphiSim comes with the TRandomStream  object that creates a stream of pseudo random numbers between 0 and 1, and the  TDistribution object, that transforms this stream of random numbers into a stream of numbers that satisfies a specific random distribution.

Objects, supplied with DelphiSim that inherit from TDistribution are:

Tnormal, a normally distributed random number stream

Texponential, an exponentially distributed random number stream

Tuniform, a uniformly distributed random number stream

Terlang, a stream that generates numbers that are erlang distributed

TWeibull a stream that generates numbers that have a Weibull distribution

TTriangular a stream that generates numbers that have a triangular distribution

DelphiSim comes with number of functions that given a basic random number stream, return a number that satisfies the distribution.


TRandomStream

Unit: Random

Description: 	Objects of this type create pseudo random numbers based on two seed numbers.

Constructor:

Create(seed1,seed2:longint)

Methods:

Uniform:double    Returns a random number beween 0 and 1

Example

var mystream: TRandomStream;	{define the stream}

    x:double;

begin

  Mystream:=Trandomstream.create(145,245);	{create the stream}

x:=Mystream.uniform;	{draw a random number}

end;


TDistribution

Unit: Random

Description: 	This abstract object is the basis for all random distribution streams. Use it to create your own. In order to do so you must define an object type that inherits from TDistribution and override the draw function. (see example)

See also: TRandomStream

Constructor:

Create(stream:TRandomStream) {based on random stream}

Methods:

Draw:double 	:You should override this function

uniform:double	:returns a random number between 0 and 1 based on the random stream passed to the object at its creation

Example:

Type TMydist = class(TDistribution){define a new distribution type}

 	  function draw:double; override;  {override the abstract draw}

     end;

implementation

{define a new function for draw based on your own distribution}

function TMyDist.draw;

begin

  {place your function here}

  {use the uniform method to obtain random numbers between 0 and 1}

end;


TNormal

Unit: Random

Description: 	Objects of type Tnormal produce a stream of normally distributed numbers. Use the inherited draw method to produce a number;

Inherits from: TDistribution

See also: TRandomStream

Constructor:

constructor create(mean,s:Double;stream:TRandomStream);

Example:

Var dist:Tnormal; {Define a new normal stream}

begin

  Dist:=Tnormal.create(7,3,MyStream); {create the stream}

  y:=Dist.draw;	   {draw a number}

end;


TUniform

Unit: Random

Description: 	Objects of type Tuniform produce a stream of uniformly distributed numbers. Use the inherited draw method to produce a number;

Inherits from: TDistribution

See also: TRandomStream

Constructor:

create(low,high:Doubl:Stream:TrandomStream)

Example:

Var dist:TUniform; {Define a new Uniform stream}

begin

  Dist:=TUniform.create(3,7,MyStream); {create the stream}

  y:=Dist.draw;	   {draw a number}

end;


TExponential

Unit: Random

Description: 	Objects of type TExponential produce a stream of exponentially distributed numbers. Use the inherited draw method to produce a number;

Inherits from: TDistribution

See also: TRandomStream

Constructor:

Create(Mean:double;Stream:TRandomStream)

Example:

Var dist:TExponential; {Define a new Exponential stream}

begin

  Dist:=TExponential.create(3, MyStream); {create the stream}

  y:=Dist.draw;	   {draw a number}

end;


TErlang

Unit: Random

Description: 	Objects of type Terlang produce a stream of numbers that have an erlang distribution. Use the inherited draw method to produce a number;

Inherits from: TDistribution

See also: TRandomStream

Constructor:

create(ExpoMean:double;K:longint;Stream:TRandomStream)

Example:

Var dist:TErlang; {Define a new Erlang stream}

begin

  Dist:=TErlang.create(4,3,MyStream); {create the stream}

  y:=Dist.draw;	   {draw a number}

end;


TWeibull

Unit: Random

Description: 	Objects of type TWeibull produce a stream of numbers that have a Weibull distribution. Use the inherited draw method to produce a number;

Inherits from: TDistribution

See also: TRandomStream

Constructor:

create(shape,scale:double;Stream:TRandomStream)

Example:

Var dist:TWeibull; {Define a new Weibull stream}

begin

  Dist:=TWeibull.create(4,3,MyStream); {create the stream}

  y:=Dist.draw;	   {draw a number}

end;


TTriangular

Unit: Random

Description: 	Objects of type TTriangular produce a stream of numbers that have a triangular distribution. Use the inherited draw method to produce a number;

Inherits from: TDistribution

See also: TRandomStream

Constructor:

create(min,modus,max:double;Stream:TRandomStream)

Example:

Var dist:TTriangular; {Define a new triangular stream}

begin

  Dist:=TTriangular.create(1,3,7,MyStream); {create the stream}

  y:=Dist.draw;	   {draw a number}

end;


Random functions

Unit: Random

Description: 	DelphiSim comes with a number of functions that return a value according to a specific distribution. These functions can be used when just on or two values are needed and the use of a random number stream is cumbersome.

These functions are:

DrawNormal(mean,s:double;stream:TrandomStream):double

DrawExpo(mean:double;TRandomStream):double

DrawErlang(mean:double;k:longint;Stream:TrandomStream):double

drawUniform(low,high:double;stream:TrandomStream):double

drawWeibull(Shape,scale:double;stream:TrandomStream):double

drawTria(min,modus,max:double;stream:TrandomStream):double

See also: 	Tnormal, Terlang, Texponential , Tuniform , TRandomStream

TWeibull , TTriangular


TTally

Unit: Tally

DelphiSim comes with Ttally, a basic object for keeping simulation statistics. It can record values and calculate their average, standard deviation etc. When creating a TTally object you set the starttime. All measurements done with a simulation time lower then the start time are ignored.

Constructor:

  create(L:TSimulation;StartTime:Double);

Methods:

  reset	      Clears all previous observations

  Tally(value:Double)  Records the value

Properties (read only):

  min:double	The lowest recorded value

  Max:double	The Highest recorded value

  avg:double	The average of all observation

  stdev:double	The Standard deviation of the observations

  count:longint	The number of observations


TMachine

Unit: Machine

Tmachine inherits from TSimProcess. It is the definition of a simple machine class. It processes jobs of type Tobject for a duration T. A job is offered to the machine by making a call to the Process method. In this call, the load and its processing time are specified.

Immediately after the job has been offered for processing, a call to the OnArrive method is made. This is a method that can be overridden by the user and can be used to do some preprocessing on the job i.e. marking the arrival time at the machine.

Jobs are handled on a first come first served basis. When the machine has finished processing a job, the Continue method is called. This is a method that can be overridden by the user in order to do some post processing of the job i.e. recording the total time in the machine and sending the job to the next machine. If the method is not overridden the job object will be destroyed.

The machine records several statistics about itself such as the time it has spent processing jobs.

Constructor:

  Create(L:TSimulation;n:String)

Methods:

  process(O:TObject;T:Double)

  OnArrival(O:TObject); virtual

Continue(O:TObject); virtual

Properties (read only):

  jobsPending:longint	Number of jobs waiting to be processed

  jobsdone:longint	Number of jobs processed

  TimeActive:double	Total time the machine has been active

Example

{

  define your machine type

}

type TmyMachine = class(Tmachine)

   procedure OnArrival(O:Tobject); override;

   Procedure Continue(O:Tobject); override;

end;

     Tjob = class(Tobject) {job type definition}

  timein:double;

     end;

implementation

procedure Tmymachine.OnArrival(O:Tobject);

begin

  (O as TJoB).timein:=simtime; {mark the arrival time}

end;

{

  On departure, register the total time spent in the machine and

  send it to the next machine with processing time expo(5)

}

procedure TmyMachine.Continue(O:Tobject);

begin

  waittimeTally.tally(simtime-(O as Tjob).timein);

  NextMachine.Process(O,DrawExpo(4,mystream));

end;


TWaitProcess

Unit: WaitProcess

TWaitProcess inherits from TSimProcess. It holds objects for a specified time before calling its Continue method. An object is ordered to wait by calling the Wait method, identifying the object and specifying the time the object should wait.

When an object has finished waiting, the Continue method is called. This is a method that can be overridden by the user in order to do some post processing of the object i.e. sending it to the next machine. If this method is not overridden, the object will be destroyed after it has finished waiting

Constructor:

  Create(L:TSimulation;StartTime:Double;n:String);

Methods:

  Wait(O:TObject;T:Double)

Continue(O:Tobject); virtual

Example

{

  define your processtype

}

type TmyWaitProcess = class(Twaitprocess)

    Procedure Continue(O:Toject); override;

  end;

implementation

{

  On departure, send it to the next machine with processing time expo(5)

}

procedure TmyWaitProcess.Continue(O:Tobject);

begin

 NextMachine.Process(O,DrawExpo(4,mystream));

end;

var proc:TMyWaitProcess

    O:Tobject;

begin

  O:=Tobject.create;

  proc:=TMyWaitProcess.create(mysim,0,’my wait process’);

  proc.wait(O,DrawNormal(10,2);

end;


TSemaphore

Unit: Semaphore

TSemaphore inherits from Tobject. A semaphore can be aquired by a simulation process. If a process atempts to aquire a semaphore that is already held by some other process, it will be rendered inactive until the semaphore has been released. A semaphore can only be released by the process that holds it.

Constructor:

 Create

Methods:

 	Aquire(P:TSimProcess)  Let Process P attempt to get the semaphore

Release(P:TSimProcess) Let process P release the semaphore

Properties (read only):

holder:TSimProcess	  The current holder of the semaphore


TOrderlist
OrderList

Unit: Ordelist

An orderlist represents a queue, where loads of type Tobject can be stored until they are explicitly ordered to continue.

Loads are put on a list by calling the  WaitToBeOrdered method.

A process can order a specific amount of these objects to continue by calling the OrderToContinue mehtod. This order can include a Backorder parameter. If the required amount of loads was not on the list, new arriving loads will be ordered to continue without the need for a new order command. The OrderToContinue method returns the number of loads that did continue.

What happens to continuing loads is specified in the the Continue method. The loads are destroyed unless this method is overridden by the user.

Constructor:

Create;

Methods:

  WaitTobeOrdered(O:TObject)

  OrderToContinue(X:Longint;backorder:boolean):longint

  Continue(O:TObject); virtual

Properties (read only):

ListSize:longint 	Number of loads on the orderlist

 	BackOrderSize:longint 	Number of backorders

Example

type TMyOrderlist = class(Torderlist)

   procedure continue(O:Tobject); override;

end;

implementation

Procedure TMyOrderlist.continue(O:Tobject);

begin

  NextMachine.process(O,drawexpo(4));

end;

.

.

.

begin {body of process1}

  X:Tobject.create;

  MyOrderlist.WaitToBeOrdered(O);

end;

begin {body of process2}

  count:=MyOrderlist.orderToContinue(5,false)

end